package com.yangff.service.impl;


import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yangff.api.client.ProductClient;
import com.yangff.api.client.UserClient;
import com.yangff.entity.product.entity.vo.FundnetvalueVo;
import com.yangff.entity.product.entity.vo.ProductVo;
import com.yangff.entity.user.entity.UserAsset;
import com.yangff.entity.user.entity.dto.UserAssetDTO;
import com.yangff.entity.user.entity.vo.RiskAssessmentVo;
import com.yangff.entity.user.entity.vo.UserAssetVo;
import com.yangff.entity.user.entity.vo.UserVo;
import com.yangff.entity.vo.ResultVo;
import com.yangff.mapper.UserAssetMapper;
import com.yangff.service.IUserAssetService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 存储用户的基金资产信息 服务实现类
 * </p>
 *
 * @author yangff
 * @since 2025-01-14
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class UserAssetServiceImpl extends ServiceImpl<UserAssetMapper, UserAsset> implements IUserAssetService {
    private final UserClient userClient;
    private final ProductClient productClient;

    //定义每种产品类型对应的风险权值
    private Map<Character,Double> riskAssessmentMap = Map.of(
            '1' , 1.0,
            '2' , 3.0,
            '3' , 6.0,
            '4' , 5.0,
            '5', 2.0,
            '6', 4.0
    );

    @Override
    public List<UserAssetVo> getUserAssetByCode(String code) {
        List<UserAsset> userAssets = list(new LambdaQueryWrapper<UserAsset>()
        .eq(UserAsset::getCode,code));
        List<UserAssetVo> userAssetVos = BeanUtil.copyToList(userAssets, UserAssetVo.class);
        return userAssetVos;
    }

    @Override
    public boolean checkAccountExist(UserAssetDTO userAssetDTO) {
        return (userClient.getUserByAccount(userAssetDTO.getAccount()) != null);
    }

    @Override
    public boolean checkProductExist(UserAssetDTO userAssetDTO) {
        return (productClient.getProductByCode(userAssetDTO.getCode()) != null);
    }

    @GlobalTransactional(rollbackFor = Exception.class)
    @Override
    public ResultVo changeUserAssetAmountAndShares(UserAssetDTO userAssetDTO) {
        if(checkAccountExist(userAssetDTO) == false || checkProductExist(userAssetDTO) == false) return ResultVo.custom("用户或产品不存在，无法绑定产品");
        UserAsset userAsset = getOne(new LambdaQueryWrapper<UserAsset>().eq(UserAsset::getAccount,userAssetDTO.getAccount()).eq(UserAsset::getCode,userAssetDTO.getCode()));

        //获取单日净值
        List<FundnetvalueVo> fundnetvalues = productClient.getFundNetValueByCode(userAssetDTO.getCode());

        //获取每个上市基金的最新净值
        Optional<FundnetvalueVo> latestFundnetvalueVo = fundnetvalues.stream().max(Comparator.comparingInt(FundnetvalueVo::getListDate));
        if(latestFundnetvalueVo.isPresent() == false) return ResultVo.custom("该产品暂未上市，无法购入");

        Double latestNetValue = latestFundnetvalueVo.get().getNetValue();



        //存在持有的资产，更新
        if(userAsset != null)
        {
            //相加小于0，删除
            if(userAsset.getAmount() + userAssetDTO.getAmount() <= 0)
            {
                remove(new LambdaQueryWrapper<UserAsset>().eq(UserAsset::getAccount,userAssetDTO.getAccount()).eq(UserAsset::getCode,userAssetDTO.getCode()));
            }
            else
            {
                //相加大于0，按照比例更新

                //还需要把买卖记录写在交易记录那边，不要忘记了

                //判断是卖出还是买入来改变更新份额方式
                boolean isSell = (userAssetDTO.getAmount() < 0 ? true : false);
                Double shares = null;
                if(isSell)
                {
                    shares = (userAsset.getAmount() + userAssetDTO.getAmount()) / userAsset.getAmount();
                    userAsset.setShares(userAsset.getShares() * shares);
                }
                else
                {
                    //买入将新买入的份额算入，这里不考虑确认份额的时间
                    shares = userAsset.getShares() + (userAssetDTO.getAmount() / latestNetValue);
                    userAsset.setShares(shares);
                }

                userAsset.setSeedMoney(userAsset.getSeedMoney() + userAssetDTO.getAmount());
                userAsset.setAmount(userAsset.getAmount() + userAssetDTO.getAmount());
                userAsset.setPurchaseDatetime(LocalDateTime.now());


                update(userAsset , new LambdaQueryWrapper<UserAsset>().eq(UserAsset::getAccount,userAssetDTO.getAccount()).eq(UserAsset::getCode,userAssetDTO.getCode()));
            }
        }
        else
        {
            if(userAssetDTO.getAmount() <= 0) return ResultVo.custom("购买数目非法，创建失败");
            //自动获取code对应的产品信息



            ProductVo productVo = productClient.getProductByCode(userAssetDTO.getCode());
            userAsset = BeanUtil.copyProperties(productVo, UserAsset.class);
            userAsset.setAmount(userAssetDTO.getAmount());
            userAsset.setAccount(userAssetDTO.getAccount());
            userAsset.setShares(userAssetDTO.getAmount() / latestNetValue);
            userAsset.setSeedMoney(userAssetDTO.getAmount());
            userAsset.setChangeRate(0.0);


            save(userAsset);
        }
        return ResultVo.success();
    }

    @Override
    public RiskAssessmentVo getRiskAssessmentByAccount(String account) {
        List<UserAssetVo> allUserAssetByAccount = userClient.getAllUserAssetByAccount(account);
        if(allUserAssetByAccount == null) return null;

        RiskAssessmentVo riskAssessmentVo = new RiskAssessmentVo();

        Double amount = 0.0,
                flag = 0.0,
                persent = 0.0;
        String flagCode = null;

        for(UserAssetVo userAssetVo : allUserAssetByAccount)
        {
            amount += userAssetVo.getAmount();
            //选出占比最大的投资类型
            if(userAssetVo.getAmount() > flag)
            {
                flag = userAssetVo.getAmount();
                flagCode = userAssetVo.getCode();
            }
        }


        for(UserAssetVo userAssetVo : allUserAssetByAccount)
        {
            //计算占比分
            persent += (userAssetVo.getAmount() / amount * riskAssessmentMap.get(userAssetVo.getCode().charAt(0)));
        }

        riskAssessmentVo.setScore(persent);
        riskAssessmentVo.setTypecode(flagCode);

        return riskAssessmentVo;
    }
}
